/*
 * @Description: 
 * @Author: ldx
 * @Date: 2022-05-31 23:39:45
 * @LastEditors: ldx
 * @LastEditTime: 2022-06-21 23:10:34
 */
import * as THREE from 'three';
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";

// shape转数组
export function parseShape(shape) {
  return shape.split(' ').map(coord => coord.split(',').map(Number));
}
const zUnitVector = new THREE.Vector3(0,0,1) //沿着z轴方向单位向量

// 计算车道边线
export function extrudeLine(cords, offset){
    if (cords.length < 2) return [] // 少于两个点，不成线段
    let pointsArray = []
    if (offset == 0) return cords
    let tangent, vertical
    let [p1, p2] = getAdjacentPoints(cords, 0)
    tangent = p1.clone().sub(p2).normalize();
    // 切线绕z轴旋转90度计算垂线
    // 绘制顺序会影响旋转后轴的角度
    vertical = tangent.clone().applyAxisAngle(zUnitVector, Math.PI / 2);

    /** 边线 */
    let first = p1.clone().add(vertical.clone().multiplyScalar(offset));
    pointsArray.push(first)


    for (let i = 1; i < cords.length - 1; i++) {
      // 三个点坐标
      let p1 = cords[i - 1];
      let p2 = cords[i];
      let p3 = cords[i + 1];
      // 计算三个点构成的两条线的方向
      let dir1 = p1.clone().sub(p2).normalize();
      let dir2 = p3.clone().sub(p2).normalize();
      // 两条直线角平分线方向
      let angleBisector = dir2.clone().add(dir1).normalize(); // 角平分线
      let angCos = dir1.clone().dot(dir2); //两条直线方向向量夹角余弦值
      let ang = Math.acos(angCos);

      // 对边 / 斜边 = sin  sideLength = 对边(车道宽度的一半) / sin
      let sideLength = (Math.abs(offset)) / Math.sin(ang / 2); //圆心与两条直接交叉点距离
      let z = dir1.clone().cross(dir2).z
      if (offset > 0) {
        if (z < 0) {    // 两个向量的叉乘得到的z方向
          sideLength = -sideLength
        }
      } else {
        if (z > 0) {
          sideLength = -sideLength
        }
      }

      if (ang * 180 / Math.PI < 35) {
        // if ((z < 0 && offset > 0) || (z > 0 && offset < 0)) {
        //   let tangent1 = p1.clone().sub(p2).normalize();
        //   let tangent2 = p2.clone().sub(p3).normalize();

        //   let vertical1 = tangent1.clone().applyAxisAngle(zUnitVector, Math.PI / 2);
        //   let vertical2 = tangent2.clone().applyAxisAngle(zUnitVector, Math.PI / 2);

        //   let offsetP = p2.clone().add(angleBisector.clone().multiplyScalar(-Math.abs(offset)))

        //   /** 边 */
        //   let a = offsetP.clone().add(vertical1.clone().multiplyScalar(offset));
        //   let b = offsetP.clone().add(vertical2.clone().multiplyScalar(offset));

        //   pointsArray.push(a, b)
        // }
        // else {
          let point = p2.clone().add(angleBisector.clone().multiplyScalar(sideLength))
          pointsArray.push(point)
        // }

      } else {
        let point = p2.clone().add(angleBisector.clone().multiplyScalar(sideLength))
        pointsArray.push(point)
      }
    }

    let [p3, p4] = getAdjacentPoints(cords, cords.length - 1)
    tangent = p3.clone().sub(p4).normalize();
    // 切线绕z轴旋转90度计算垂线
    vertical = tangent.clone().applyAxisAngle(zUnitVector, Math.PI / 2);
    let second = cords[cords.length - 1]
    let endpoint = second.clone().add(vertical.clone().multiplyScalar(offset));
    pointsArray.push(endpoint)

    return pointsArray
}
/** 获取前后相邻两个点 */
function getAdjacentPoints(cords, i) {
  let p1 = null
  let p2 = null
  if (cords[i + 1]) {
    p1 = cords[i]
    p2 = cords[i + 1]
  } else {
    p1 = cords[i - 1]
    p2 = cords[i]
  }
  return [p1, p2]
}
let scene,renderer,camera
function init(){
  /** 创建场景 */
  scene = new THREE.Scene();
  /** 相机设置 */
  const width = window.innerWidth; //窗口宽度
  const height = window.innerHeight; //窗口高度
  const k = width / height; //窗口宽高比
  const s = 200; //三维场景显示范围控制系数，系数越大，显示的范围越大
  //创建相机对象
  camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
  camera.position.set(0, 0, 500); //设置相机位置
  camera.lookAt(scene.position); //设置相机方向(指向的场景对象)
  /** 创建渲染器对象 */
  renderer = new THREE.WebGLRenderer({
     antialias: true //开启抗锯齿
  });
  renderer.setPixelRatio(window.devicePixelRatio)
  renderer.setSize(width, height); //设置渲染区域尺寸
  // renderer.setClearColor(0x888888, 1); //设置背景颜色
  document.body.appendChild(renderer.domElement); //body元素中插入canvas对象
  const controls = new OrbitControls(camera, renderer.domElement)
  controls.addEventListener("change", () => {
    render()
  }); //监听鼠标、键盘事件
}

function render(){
  renderer.render(scene, camera); //执行渲染操作
}

function drawEdge(){
  // 路网数据
  const edge = {
    id: ":10_2",
    lane: [
      // {
      //   id: ":10_2_0",
      //   index: "0",
      //   speed: "6.49",
      //   length: "9.03",
      //   shape: "-200,-80 -120,-80 -116.10287141376428,-79.8251685447757 -112.4114856550571,-79.30067417910278 -108.92584272387845,-78.42651690298123 -105.64594262022837,-77.20269671641107 -102.57178534410684,-75.62921361939232 -99.70337089551384,-73.70606761192494 -97.04069927444941,-71.43325869400893 -94.58377048091351,-68.81078686564432 -92.33258451490616,-65.83865212683108 -90.28714137642736,-62.51685447756925 -9.712858623572641,82.51685447756924 -7.688530046893857,85.7492094077311 -5.500687766286559,88.45301598924436 -3.149331781750745,90.62827422210898 -0.6344620932864191,92.27498410632506 2.0439212991064193,93.39314564189253 4.885818395427771,93.98275882881138 7.891229195677637,94.04382366708165 11.060153699856022,93.57634015670331 14.392591907962913,92.58030829767638 17.88854381999832,91.05572809000084 82.11145618000168,58.94427190999916 85.51027950580136,57.04486024709932 88.55133195520109,54.92433402239948 91.23461352820081,52.58269323589958 93.5601242248006,50.019937887599696 95.52786404500043,47.236067977499786 97.13783298880027,44.23108350559986 98.39003105620014,41.004984471899924 99.28445824720008,37.55777087639997 99.82111456180002,33.88944271909999 100,30 100,-80 99.8,-83.80000000000001 99.20000000000003,-87.20000000000002 98.2,-90.19999999999999 96.8,-92.8 95,-95 92.8,-96.80000000000001 90.2,-98.2 87.2,-99.20000000000002 83.80000000000001,-99.8 80,-100 20,-100 16.200000000000003,-99.8 12.800000000000002,-99.20000000000003 9.799999999999999,-98.2 7.199999999999999,-96.8 5,-95 3.2000000000000006,-92.8 1.8000000000000005,-90.2 0.7999999999999996,-87.2 0.1999999999999999,-83.80000000000001 0,-80 0,-20"
      // },
      // {
      //   id: ":10_2_1",
      //   index: "1",
      //   speed: "6.49",
      //   length: "9.03",
      //   shape: "-200,-76.8 -120.07174249446317,-76.8 -116.4003441712357,-76.63529516736375 -113.02745314515533,-76.15605445538043 -109.8773354502552,-75.36604286842048 -106.93862106603895,-74.26952837946833 -104.19740088443477,-72.866456502026 -101.63964118984677,-71.15159087404092 -99.25394920350898,-69.1152068231298 -97.03352243563866,-66.74517206224996 -94.97656999579299,-64.02947469434446 -93.04960342471512,-60.90008287425552 -12.46942546440264,84.14423745430692 -10.297865765836585,87.61168428021546 -7.843147402349116,90.64530499674927 -5.126064731380469,93.1588999131588 -2.140091071062526,95.1140836600578 1.0938547703036265,96.46417934023354 4.525231070777264,97.17609277251755 8.09363762843915,97.24859672748705 11.755452305815954,96.70840147276328 15.494386020158732,95.5908722446997 19.24460145838385,93.95540803480773 83.60832411315658,61.773546707421374 87.21016276516734,59.76068116905067 90.52432495378595,57.44971549160516 93.47911165738414,54.871138151763 96.06080424681235,52.02606566901881 98.25514039199392,48.921617456655426 100.05050632896065,45.57059209511663 101.44064849249891,41.98910094986305 102.42557739369833,38.193084535134275 103.01042954463101,34.19531248856262 103.2,30.073549225936986 103.2,-80.08415228940945 102.98529730157514,-84.16350355948173 102.3103374084508,-87.98827628718652 101.1484482243781,-91.47394383940451 99.47157717737899,-94.58813292668857 97.2740272645683,-97.2740272645683 94.58813292668857,-99.471577177379 91.47394383940451,-101.1484482243781 87.9882762871865,-102.31033740845079 84.16350355948174,-102.98529730157514 80.08415228940945,-103.2 19.915847710590565,-103.2 15.836496440518284,-102.98529730157514 12.01172371281351,-102.3103374084508 8.526056160595473,-101.1484482243781 5.41186707331142,-99.47157717737899 2.7259727354316965,-97.2740272645683 0.528422822621013,-94.58813292668857 -1.1484482243781,-91.47394383940451 -2.3103374084507733,-87.9882762871865 -2.985297301575142,-84.16350355948175 -3.2000000000000006,-80.08415228940943 -3.2,-20"
      // },
      {
        id: ":10_2_2",
        index: "2",
        speed: "6.49",
        length: "9.03",
        shape: "-200,-73.6 -120.14348498892633,-73.6 -116.69781692870713,-73.4454217899518 -113.64342063525356,-73.01143473165807 -110.82882817663196,-72.30556883385972 -108.23129951184953,-71.33636004252558 -105.82301642476271,-70.10369938465968 -103.57591148417968,-68.59711413615689 -101.46719913256857,-66.79715495225066 -99.4832743903638,-64.67955725885561 -97.62055547667981,-62.220297261857844 -95.81206547300287,-59.28331127094181 -15.225992305232639,85.7716204310446 -12.907201484779316,89.47415915269981 -10.185607038411677,92.83759400425417 -7.102797681010186,95.68952560420863 -3.645720048838631,97.95318321379054 0.14378824150083214,99.53521303857455 4.164643746126757,100.36942671622371 8.29604606120067,100.45336978789246 12.450750911775883,99.84046278882326 16.596180132354554,98.60143619172301 20.600659096769384,96.85508797961462 85.10519204631149,64.60282150484359 88.91004602453332,62.47650209100202 92.4973179523708,59.975096960810845 95.72360978656747,57.159583067626414 98.56148426882409,54.03219345043794 100.98241673898741,50.60716693581106 102.96317966912103,46.910100684633406 104.49126592879767,42.973217427826185 105.56669654019659,38.82839819386858 106.199744527462,34.50118225802525 106.4,30.14709845187397 106.4,-80.16830457881888 106.17059460315029,-84.52700711896344 105.42067481690158,-88.77655257437303 104.0968964487562,-92.74788767880904 102.14315435475798,-96.37626585337715 99.5480545291366,-99.5480545291366 96.37626585337715,-102.143154354758 92.74788767880902,-104.0968964487562 88.776552574373,-105.42067481690157 84.52700711896347,-106.17059460315029 80.16830457881886,-106.4 19.83169542118114,-106.4 15.47299288103656,-106.17059460315029 11.223447425627015,-105.42067481690158 7.2521123211909515,-104.0968964487562 3.623734146622839,-102.14315435475798 0.4519454708633903,-99.5480545291366 -2.1431543547579746,-96.37626585337715 -4.0968964487562,-92.74788767880902 -5.420674816901545,-88.776552574373 -6.170594603150285,-84.52700711896348 -6.400000000000001,-80.16830457881886 -6.3999999999999995,-20"
      }
     
    ]
  }

  edge.lane.map((lane,index) => {
    const cords = parseShape(lane.shape).map(coord=> new THREE.Vector3(coord[0],coord[1]))
    /** 计算车道边线 */
    // 获取车道宽度
    const width = lane.width || 3.2
    // 计算车道左右两条边线的顶点坐标
    const left = extrudeLine(cords, width/2)
    const right = extrudeLine(cords, -width/2)
    if(index < edge.lane.length-1){
      // 绘制车道线
      const geometry = new THREE.BufferGeometry().setFromPoints(right)
      // 线条渲染模式
      const material = new THREE.LineDashedMaterial({
        color: 0xffffff, //线条颜色
        dashSize: 2, // 虚线的大小
        gapSize: 3, // 两个虚线直接间隙的大小
      });
      // 创建线模型对象   构造函数：Line、LineLoop、LineSegments
      const line = new THREE.Line( geometry, material );
      line.computeLineDistances();
      line.renderOrder = 10
      // 把物体添加进场景中
      scene.add( line );
    }
    // 根据顶点坐标自定义形状
    const heartShape = new THREE.Shape(left.concat(right.slice().reverse()));
    // 创建一个顶点缓冲几何体
    const laneGeometry = new THREE.ShapeGeometry( heartShape );
    const laneMaterial = new THREE.MeshBasicMaterial( { 
      color: '#5c83a1',
      side:THREE.FrontSide // 显示的面 THREE.FrontSide	背面 THREE.BackSide	前面 THREE.DoubleSide	双面
    } );
    // 创建线模型对象   构造函数：Line、LineLoop、LineSegments
    const laneMesh = new THREE.Mesh( laneGeometry, laneMaterial );
    laneMesh.name = `车道${index+1}`
    // 把物体添加进场景中
    scene.add( laneMesh );
  })  
}

init()
drawEdge()
render()

